package com.willian.andrappfw.utils;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.Color;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkInfo;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;

import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AlertDialog;

import com.willian.andrappfw.R;
import com.willian.andrappfw.application.WApplication;
import com.willian.andrappfw.bean.FileBean;
import com.willian.andrappfw.greendao.DaoSession;
import com.willian.andrappfw.greendao.FileBeanDao;
import com.willian.andrappfw.network.WApiRetrofit;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class Utils {
    public Utils() {
    }

    private static Handler handler;

    public static void initHandler() {
        new Thread(() -> {
            Looper.prepare();
            handler = new Handler();
            Looper.loop();
        }).start();
    }

    public static Handler getHandler() {
        return handler;
    }

    public static WApplication getApplicationContext() {
        return WApplication.ContextHolder.getContext();
    }

    public static int getScreenWidth() {
        return getApplicationContext().getResources().getDisplayMetrics().widthPixels;
    }

    public static int getScreenHeight() {
        return getApplicationContext().getResources().getDisplayMetrics().heightPixels;
    }

    /**
     * 获取状态栏高度
     */
    public static int getStatusBarHeight() {
        Resources resources = getApplicationContext().getResources();
        int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");
        return resources.getDimensionPixelSize(resourceId);
    }

    public static String getTimeZone() {
        return "de";
    }

    public static String getLanguage() {
        return "en-US";
    }

    /**
     * 用户名和密码拼接后MD5加密作为密码
     */
    public static String encryptNamePwd(String name, String pwd) throws Exception {
        return Utils.getMD5(name + "-" + pwd);
    }

    public static boolean isLogin() {
        return !TextUtils.isEmpty(WPreferenceManager.getInstance().getString(PreferenceKeys.TOKEN, null));
    }

    // 将时间戳转为字符串
    public static String timeStampTotimeString(String timeStamp, String format) {

        String re_StrTime = null;
        SimpleDateFormat sdf = new SimpleDateFormat(format);

        long lcc_time = Long.valueOf(timeStamp);
        return sdf.format(new Date(lcc_time));
    }

    public static String getEnglishLetterMothString(String month) {
        switch (month) {
            case "01": {
                return "Jan";
            }
            case "02": {
                return "Feb";
            }
            case "03": {
                return "Mar";
            }
            case "04": {
                return "Apr";
            }
            case "05": {
                return "May";
            }
            case "06": {
                return "Jun";
            }
            case "07": {
                return "Jul";
            }
            case "08": {
                return "Aug";
            }
            case "09": {
                return "Sep";
            }
            case "10": {
                return "Oct";
            }
            case "11": {
                return "Nov";
            }
            case "12": {
                return "Dec";
            }
        }

        return "";
    }

    public static String getString(int strResId) {
        return getApplicationContext().getString(strResId);
    }

    //判断字符串是不是空的
    public static boolean isEmpty(String str) {
        if (str == null || str.length() <= 0) {
            return true;
        } else {
            return false;
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.M)
    public static int getColor(int colorResId) {
        return getApplicationContext().getColor(colorResId);
    }

    public static String getReadableTime(long timeMillis) {
        Date date = new Date(timeMillis);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss", Locale.getDefault());
        return sdf.format(date);
    }

    public static DaoSession getDaoSession() {
        return getApplicationContext().getDaoSession();
    }


    public static List<FileBean> getFileList() {
        return Utils.getDaoSession().getSDFileBeanDao().queryBuilder().where(FileBeanDao.Properties.UserId.eq(WPreferenceManager.getUserId())).list();
    }

    public static String getSerialNumber() {
        String serial = null;
        try {
            Class<?> c = Class.forName("android.os.SystemProperties");
            Method get = c.getMethod("get", String.class);
            serial = (String) get.invoke(c, "ro.serialno");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return serial;
    }

    public static boolean isNetworkAvailable() {
        Object obj = getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
        if (obj instanceof ConnectivityManager) {
            ConnectivityManager connectivityManager = (ConnectivityManager) obj;
            Network[] networks = connectivityManager.getAllNetworks();
            NetworkInfo networkInfo;
            for (Network mNetwork : networks) {
                networkInfo = connectivityManager.getNetworkInfo(mNetwork);
                if (networkInfo != null && networkInfo.getState().equals(NetworkInfo.State.CONNECTED)) {
                    return true;
                }
            }
        }
        return false;
    }

    @RequiresApi(api = Build.VERSION_CODES.M)
    public static void setAlertDialogButtonTextColor(AlertDialog d, int positiveButtonColor, int negativeButtonColor) {
        d.getButton(d.BUTTON_POSITIVE).setTextColor(getColor(positiveButtonColor));
        d.getButton(d.BUTTON_NEGATIVE).setTextColor(getColor(negativeButtonColor));

        d.getButton(d.BUTTON_POSITIVE).setBackgroundColor(Color.TRANSPARENT);
        d.getButton(d.BUTTON_NEGATIVE).setBackgroundColor(Color.TRANSPARENT);

        d.getButton(d.BUTTON_POSITIVE).setForeground(d.getContext().getDrawable(R.drawable.ripple_grey));
        d.getButton(d.BUTTON_NEGATIVE).setForeground(d.getContext().getDrawable(R.drawable.ripple_light));
    }

    public static void downloadFile(String url, String fileName, final DownloadListener downloadListener) {
        String path = WApplication.ContextHolder.getContext().getFilesDir() + "/" + fileName;
        File file = new File(path);
        //通过Url得到文件并创建本地文件
        if (file.exists()) {
            file.delete();
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        Call<ResponseBody> mCall = WApiRetrofit.getInstance().downloadFile(url);
        mCall.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                //保存到本地
                Thread mThread = new Thread() {
                    @Override
                    public void run() {
                        super.run();
                        //保存到本地
                        writeFile2Disk(response, file, downloadListener);
                    }
                };
                mThread.start();
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                downloadListener.onFailure();
            }
        });
    }

    //将下载的文件写入本地存储
    private static void writeFile2Disk(Response<ResponseBody> response, File file, DownloadListener downloadListener) {
        downloadListener.onStart();
        long currentLength = 0;
        OutputStream os = null;

        InputStream is = response.body().byteStream(); //获取下载输入流
        long totalLength = response.body().contentLength();

        try {
            os = new FileOutputStream(file); //输出流
            int len;
            byte[] buff = new byte[1024];
            while ((len = is.read(buff)) != -1) {
                os.write(buff, 0, len);
                currentLength += len;
                //计算当前下载百分比，并经由回调传出
                downloadListener.onProgress((int) (100 * currentLength / totalLength));
                //当百分比为100时下载结束，调用结束回调，并传出下载后的本地路径
                if ((int) (100 * currentLength / totalLength) == 100) {
                    downloadListener.onFinish(); //下载完成
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (os != null) {
                try {
                    os.close(); //关闭输出流
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (is != null) {
                try {
                    is.close(); //关闭输入流
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public interface DownloadListener {
        void onStart();

        void onProgress(int currentLength);

        void onFinish();

        void onFailure();
    }

    public static String getMD5(String str) {
        MessageDigest md = null;

        try {
            md = MessageDigest.getInstance("MD5");
            md.update(str.getBytes());
            return (new BigInteger(1, md.digest())).toString(16);
        } catch (NoSuchAlgorithmException var3) {
            var3.printStackTrace();
            return null;
        }
    }

    public static String getFileMD5(File file) {
        if (!file.isFile()) {
            return null;
        } else {
            MessageDigest digest = null;
            FileInputStream in = null;
            byte[] buffer = new byte[1024];

            try {
                digest = MessageDigest.getInstance("MD5");
                in = new FileInputStream(file);

                int len;
                while((len = in.read(buffer, 0, 1024)) != -1) {
                    digest.update(buffer, 0, len);
                }

                in.close();
                return bytesToHexString(digest.digest());
            } catch (Exception var6) {
                var6.printStackTrace();
                return null;
            }
        }
    }

    public static String bytesToHexString(byte[] src) {
        StringBuilder stringBuilder = new StringBuilder("");
        if (src != null && src.length > 0) {
            for(int i = 0; i < src.length; ++i) {
                int v = src[i] & 255;
                String hv = Integer.toHexString(v);
                if (hv.length() < 2) {
                    stringBuilder.append(0);
                }

                stringBuilder.append(hv);
            }

            return stringBuilder.toString();
        } else {
            return null;
        }
    }

    public static void unzip(InputStream stream, String destination) {
        dirChecker(destination, "");
        byte[] buffer = new byte[10240];

        try {
            ZipInputStream zin = new ZipInputStream(stream);

            while(true) {
                ZipEntry ze;
                while((ze = zin.getNextEntry()) != null) {
                    if (ze.isDirectory()) {
                        dirChecker(destination, ze.getName());
                    } else {
                        File f = new File(destination, ze.getName());
                        if (!f.exists()) {
                            boolean success = f.createNewFile();
                            if (!success) {
                                LogUtils.e("Failed to create file " + f.getName());
                            } else {
                                FileOutputStream fout = new FileOutputStream(f);

                                int count;
                                while((count = zin.read(buffer)) != -1) {
                                    fout.write(buffer, 0, count);
                                }

                                zin.closeEntry();
                                fout.close();
                            }
                        }
                    }
                }

                zin.close();
                break;
            }
        } catch (Exception var9) {
            var9.printStackTrace();
        }

    }

    private static void dirChecker(String destination, String dir) {
        File f = new File(destination, dir);
        if (!f.isDirectory()) {
            boolean success = f.mkdirs();
            if (!success) {
                LogUtils.e("Failed to create folder " + f.getName());
            }
        }

    }

    public static boolean checkAppInstalled(Context context, String pkgName) {
        if (pkgName != null && !pkgName.isEmpty()) {
            PackageInfo packageInfo;
            try {
                packageInfo = context.getPackageManager().getPackageInfo(pkgName, 0);
            } catch (PackageManager.NameNotFoundException var4) {
                packageInfo = null;
                var4.printStackTrace();
            }

            return packageInfo != null;
        } else {
            return false;
        }
    }

    public static String maskString(String str, int keepHead, int keepEnd) {
        if (!TextUtils.isEmpty(str) && keepHead + keepEnd < str.length()) {
            StringBuilder sb = new StringBuilder(str);

            for(int i = keepHead; i < str.length() - keepEnd; ++i) {
                sb.replace(i, i + 1, "*");
            }

            return sb.toString();
        } else {
            return str;
        }
    }
}

